<?php
/**
 * Created by IntelliJ IDEA.
 * User: lee
 * Date: 2018/2/1
 * Time: 下午2:11
 *
 *
 * 该订单号计算算法目前支持到用户UID在亿级以内
 */

namespace Biz\tools;

use Biz\model\trade\Order;
use Doraemon\pockets\constInterface\AppType;
use Doraemon\tools\HhzEnv;
use Doraemon\tools\IdParse;

class OrderNo
{


    const TYPE_ORDER_NO = 'O';//订单号前缀
    const TYPE_TEST_ORDER_NO = 'C';//测试环境订单号前缀
    const TYPE_GROUP_ORDER_NO = 'T';//团购订单号前缀
    const TYPE_PARAGRAPH_ORDER_NO = 'P';//节选订单号前缀

    const TYPE_REFUND_ORDER_NO = 'OR';//退款订单号前缀
    const TYPE_TEST_REFUND_ORDER_NO = 'CR';//退款订单号前缀测试环境

    const TYPE_AUTO_REFUND_ORDER_NO = 'AR';//重复订单自动退款前缀
    const TYPE_TEST_AUTO_REFUND_ORDER_NO = 'CAR';//重复订单自动退款前缀测试环境


    const ORDER_NO_FLAG_P = 'P';//父单号

    const DEFAULE_ORDER_SEPARATOR = '-';

    //生成订单号
    public static function genNo($uid, $shopIds, $appType = 0, $orderType = 0, $store = '')
    {

        $data = [];

        if (!is_array($shopIds)) {
            $shopIds = [$shopIds];
        }

        $l = count($shopIds) + 1;

        $microTime = bcmul(microtime(true), 10000);

        $microTime = sprintf('%s%s', date('His'), substr($microTime, -4, 3));

        $microTime = strtoupper(base_convert($microTime, 10, 32));

        $time = date('ymd');

        $hashUid = IdParse::hashUid($uid);

        $type = 'order';
        if ($orderType && $orderType == Order::ORDER_TYPE_GROUP_BUY) {
            $type = 'order_group';
        } else if ($appType && $appType == AppType::APPTYPE_PARAGRAPH_MINIPROGRAM) {
            $type = 'paragraph';
        }
        $prefix = self::prefixOrderNo($type, $store);

        for ($i = 0; $i < $l; $i++) {

            $order = [
                $prefix . $time,
                $microTime,
                $hashUid
            ];

            if ($i == $l - 1) {
                $order[] = self::ORDER_NO_FLAG_P;
                $data['P'] = implode('-', $order);
            } else {
                $order[] = $i + 1;

                $data[$shopIds[$i]] = implode('-', $order);
            }
        }
        return $data;
    }

    protected static function prefixOrderNo($type = 'order', $store = 'BJ')
    {
        $prefix = '';
        $isTest = (HhzEnv::isShopHaoHaoCe() || HhzEnv::isShopTest());

        switch ($type) {
            case 'order':
                $prefix = $isTest ? self::TYPE_TEST_ORDER_NO : self::TYPE_ORDER_NO;
                break;
            case 'order_group':
                $prefix = self::TYPE_GROUP_ORDER_NO;
                break;
            case 'paragraph':
                if ($store) {
                    $prefix = $store;
                } else {
                    $prefix = 'BJ';
                }
                break;
            case 'refund':
                $prefix = $isTest ? self::TYPE_TEST_REFUND_ORDER_NO : self::TYPE_REFUND_ORDER_NO;
                break;
            case 'auto_refund':
                $prefix = $isTest ? self::TYPE_TEST_AUTO_REFUND_ORDER_NO : self::TYPE_AUTO_REFUND_ORDER_NO;
                break;
        }

        return $prefix;
    }


    //生成退款订单号
    public static function genRefundNo($orderNo, $type = self::TYPE_REFUND_ORDER_NO)
    {
        if ($type == self::TYPE_REFUND_ORDER_NO) {
            $type = 'refund';
        } elseif ($type == self::TYPE_AUTO_REFUND_ORDER_NO) {
            $type = 'auto_refund';
        }

        $prefix = self::prefixOrderNo($type);

        return self::genOtherNo($orderNo, $prefix);
    }

    //判断是否是父单号
    public static function isParentNo($orderNo)
    {
        if (empty($orderNo)) {
            return false;
        }

        $data = explode('-', $orderNo);

        if (isset($data[3])) {
            if ($data[3] === 'P') {
                return true;
            }
        }

        return false;
    }

    public static function getParentNo($orderNo)
    {
        $data = explode('-', $orderNo);
        if (isset($data[3])) {
            $data[3] = 'P';
        }
        return implode('-', $data);
    }

    //获取用于支付系统的带支付版本的支付订单号
    public static function getPayOrderNo($orderNo, $payVer)
    {
        if (empty($orderNo)) {
            return false;
        }
        if ($payVer) {
            return $orderNo . self::DEFAULE_ORDER_SEPARATOR . $payVer;
        } else {
            return $orderNo;
        }
    }

    //转化支付系统的的订单号为订单系统的订单号
    public static function getOrderNoByPayOrderNo($payOrderNO)
    {
        if (empty($payOrderNO)) {
            return false;
        }
        $data = explode(self::DEFAULE_ORDER_SEPARATOR, $payOrderNO);
        if (count($data) == 5) {
            $payVer = $data[4];
            unset($data[4]);
            return [
                'order_no' => implode(self::DEFAULE_ORDER_SEPARATOR, $data),
                'pay_ver' => $payVer
            ];
        } else {
            return [
                'order_no' => $payOrderNO,
                'pay_ver' => 0
            ];
        }
    }

    //获取订单的用户uid
    public static function getOrderUid($orderNo)
    {
        if (empty($orderNo)) {
            return false;
        }

        $data = explode('-', $orderNo);

        if (isset($data[2])) {
            return IdParse::unHashUid($data[2]);
        }

        return false;
    }

    protected static function genOtherNo($orderNo, $modifyPrefix)
    {
        $nowTime = substr(bcmul(microtime(true), 10000), 0, -1);

        $orderInfo = explode('-', $orderNo);

        $orderDay = sprintf('20%s', substr($orderInfo[0], 1, 6));

        $orderRand = base_convert($orderInfo[1], 32, 10);

        $orderTime = substr($orderRand, 0, 6);

        $orderTimeStamp = strtotime(sprintf('%s%s', $orderDay, $orderTime)) . substr($orderRand, 6, 3);

        $subTime = bcsub($nowTime, $orderTimeStamp);

        $subTime = intval($subTime);

        $subTime = base_convert($subTime, 10, 32);

        $subTime = strtoupper($subTime);

        $prefix = self::prefixOrderNo();

        return sprintf('%s-%s', preg_replace('/^' . $prefix . '/', $modifyPrefix, $orderNo), $subTime);
    }


}